package com.github.zyf.ioaj.utils.basedata;

/**
 * @author zyf
 */
public class MathUtils {

    /**
     * Gamma函数
     *
     * @param x 参数
     * @return double
     */
    public static double gamma(double x) {
        return gamma(x, 1E-6);
    }

    /**
     * Gamma函数
     *
     * @param x             参数
     * @param setAbsRelaErr 误差
     * @return double
     */
    public static double gamma(double x, double setAbsRelaErr) {
        // 如果是整数就直接用阶乘
        if (Math.round(x) - x < 1E-10) return factorial((int) x);
        // 递归结束条件
        if (x < 0) {
            return gamma(x + 1, setAbsRelaErr) / x;
        }
        if (Math.abs(1.0 - x) < 1E-10) {
            return 1;
        }
        if (Math.abs(0.5 - x) < 1E-10) {
            return Math.sqrt(3.1415926);
        }

        if (x > 1.0) {
            return (x - 1) * gamma(x - 1, setAbsRelaErr);
        }

        double res = 0.0;
        double temp = 1.0;
        double check = 0.0;
        int i = 1;
        while (Math.abs((check - temp) / temp) > setAbsRelaErr) {
            check = temp;
            temp *= i / (x - 1 + i);
            i++;
        }
        res = temp * Math.pow(i, x - 1);
        return res;
    }

    /**
     * 计算阶乘
     *
     * @param x 正整数
     * @return int
     */
    public static int factorial(int x) {
        if (x < 0) return -1;
        int i;
        int f = 1;
        for (i = 1; i <= x; i++) {
            f *= i;
        }
        return f;
    }

}
